using System;

namespace KodeIT.Web
{
    /// <summary>
    /// This class represents the event raised by IIS when it is either reading or sending raw data. If your HttpFilter should 
    /// be notified for this event, it should subscribe for the <see cref="IFilterEvents.ReadRawData"/> or 
    /// <see cref="IFilterEvents.SendRawData"/> events.
    /// </summary>
    /// <remarks>
    /// The <see cref="IFilterEvents.RawData"/> or <see cref="IFilterEvents.SendRawData"/> events are raised by IIS 
    /// allowing HttpFilters to replace or modify the raw data being sent or received.
    /// </remarks>
    public class RawDataEvent : ContextEvent
    {
        private byte[] _data;
        private int _length;
        private bool _setted;

        internal RawDataEvent(NativeContext nativeContext, int rawLength)
            : base(nativeContext)
        {
            _length = rawLength;
        }

        /// <summary>
        /// Returns the data that IIS is either receiving or sending.
        /// </summary>
        /// <returns>An array of bytes of the data IIS is either receiving or sending.</returns>
        public byte[] GetData()
        {
            if( !_setted )
            {
                if (null == _data)
                {
                    _data = new byte[_length];
                    NativeMethods.ReadRaw(NativeContext, _data);
                }
            }

            return _data;
        }

        /// <summary>
        /// Modifies the data IIS is either receiving or sending.
        /// </summary>
        /// <param name="data">The new array of bytes replacing the received or to be sent data by IIS.</param>
        public void SetData(byte[] data)
        {
            if (null == data)
            {
                throw new ArgumentNullException("data",
                    "The data cannot be null");
            }

            _setted = true;
            _data = data;
        }

        internal override FilterStatus Update()
        {
            if (_setted)
            {
                NativeMethods.WriteRaw(NativeContext, _data);
            }

            return base.Update();
        }
    }
}
